//===--- SerializationOptions.h - Control swiftmodule emission --*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef POLARPHP_SERIALIZATION_SERIALIZATIONOPTIONS_H
#define POLARPHP_SERIALIZATION_SERIALIZATIONOPTIONS_H

#include "polarphp/basic/LLVM.h"

namespace polar {

class SerializationOptions {
   SerializationOptions(const SerializationOptions &) = delete;
   void operator=(const SerializationOptions &) = delete;

public:
   SerializationOptions() = default;
   SerializationOptions(SerializationOptions &&) = default;
   SerializationOptions &operator=(SerializationOptions &&) = default;
   ~SerializationOptions() = default;

   const char *OutputPath = nullptr;
   const char *DocOutputPath = nullptr;
   const char *SourceInfoOutputPath = nullptr;

   StringRef GroupInfoPath;
   StringRef ImportedHeader;
   StringRef ModuleLinkName;
   StringRef ModuleInterface;
   ArrayRef<std::string> ExtraClangOptions;

   /// Describes a single-file dependency for this module, along with the
   /// appropriate strategy for how to verify if it's up-to-date.
   class FileDependency {
      /// The size of the file on disk, in bytes.
      uint64_t Size : 62;

      /// A dependency can be either hash-based or modification-time-based.
      bool IsHashBased : 1;

      /// The dependency path can be absolute or relative to the SDK
      bool IsSDKRelative : 1;

      union {
         /// The last modification time of the file.
         uint64_t ModificationTime;

         /// The xxHash of the full contents of the file.
         uint64_t ContentHash;
      };

      /// The path to the dependency.
      std::string Path;

      FileDependency(uint64_t size, bool isHash, uint64_t hashOrModTime,
                     StringRef path, bool isSDKRelative):
         Size(size), IsHashBased(isHash), IsSDKRelative(isSDKRelative),
         ModificationTime(hashOrModTime), Path(path) {}
   public:
      FileDependency() = delete;

      /// Creates a new hash-based file dependency.
      static FileDependency
      hashBased(StringRef path, bool isSDKRelative, uint64_t size, uint64_t hash) {
         return FileDependency(size, /*isHash*/true, hash, path, isSDKRelative);
      }

      /// Creates a new modification time-based file dependency.
      static FileDependency
      modTimeBased(StringRef path, bool isSDKRelative, uint64_t size, uint64_t mtime) {
         return FileDependency(size, /*isHash*/false, mtime, path, isSDKRelative);
      }

      /// Updates the last-modified time of this dependency.
      /// If the dependency is a hash-based dependency, it becomes
      /// modification time-based.
      void setLastModificationTime(uint64_t mtime) {
         IsHashBased = false;
         ModificationTime = mtime;
      }

      /// Updates the content hash of this dependency.
      /// If the dependency is a modification time-based dependency, it becomes
      /// hash-based.
      void setContentHash(uint64_t hash) {
         IsHashBased = true;
         ContentHash = hash;
      }

      /// Determines if this dependency is hash-based and should be validated
      /// based on content hash.
      bool isHashBased() const { return IsHashBased; }

      /// Determines if this dependency is absolute or relative to the SDK.
      bool isSDKRelative() const { return IsSDKRelative; }

      /// Determines if this dependency is hash-based and should be validated
      /// based on modification time.
      bool isModificationTimeBased() const { return !IsHashBased; }

      /// Gets the modification time, if this is a modification time-based
      /// dependency.
      uint64_t getModificationTime() const {
         assert(isModificationTimeBased() &&
                "cannot get modification time for hash-based dependency");
         return ModificationTime;
      }

      /// Gets the content hash, if this is a hash-based
      /// dependency.
      uint64_t getContentHash() const {
         assert(isHashBased() &&
                "cannot get content hash for mtime-based dependency");
         return ContentHash;
      }

      StringRef getPath() const { return Path; }
      uint64_t getSize() const { return Size; }
   };
   ArrayRef<FileDependency> Dependencies;

   bool AutolinkForceLoad = false;
   bool EnableNestedTypeLookupTable = false;
   bool SerializeAllPIL = false;
   bool SerializeOptionsForDebugging = false;
   bool IsSIB = false;
};

} // end namespace polar

#endif // POLARPHP_SERIALIZATION_SERIALIZATIONOPTIONS_H
